package org.mili.ticketeer.dao;

import org.mili.application.dao.AbstractDao;
import org.mili.application.dao.DaoException;
import org.mili.application.dao.ModificationResult;
import org.mili.application.dao.RowTransformer;
import org.mili.application.dao.query.QueryBuilder;
import org.mili.application.dto.Identifieable;
import org.mili.ticketeer.dto.State;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class StateDao extends AbstractDao {

    private Map<String, State> cache = new HashMap<>();
    private Map<Integer, State> idCache = new HashMap<>();

    public StateDao() {
        super(State.Fields.values(), State.Fields.values(), State.TABLE);
    }

    public ModificationResult write(final State state) throws DaoException {
        cache.clear();
        idCache.clear();
        return createOrUpdate(state);
    }

    public State findByToken(final String token) throws DaoException {
        State state = cache.get(token.toLowerCase());
        if (state == null) {
            state = (State) readSingle(new RowTransformer<State>() {
                @Override
                public State transform(ResultSet resultSet) throws SQLException {
                    State state = new State();
                    state.setId(resultSet.getInt(Identifieable.Fields.ID.name()));
                    state.setToken(resultSet.getString(State.Fields.TOKEN.name()));
                    state.setTitle(resultSet.getString(State.Fields.TITLE.name()));
                    return state;
                }
            }, QueryBuilder.createQueryBuilder()
                    .select()
                    .fields(Identifieable.Fields.ID, fields)
                    .from(table)
                    .where()
                    .eq(State.Fields.TOKEN, token)
                    .build());
            cache.put(token.toLowerCase(), state);
        }
        return state;
    }

    public State findById(final int id) throws DaoException {
        State state = idCache.get(id);
        if (state == null) {
            state = (State) readSingle(
                    new StateRowTransformer(),
                    QueryBuilder.createQueryBuilder()
                            .select()
                            .fields(Identifieable.Fields.ID, fields)
                            .from(table)
                            .where()
                            .eq(Identifieable.Fields.ID, id)
                            .build());
            idCache.put(id, state);
        }
        return state;
    }

    public List<State> getStates() throws DaoException {
        return read(new StateRowTransformer());
    }

    static class StateRowTransformer implements RowTransformer<State> {
        @Override
        public State transform(ResultSet resultSet) throws SQLException {
            State state = new State();
            state.setId(resultSet.getInt(Identifieable.Fields.ID.name()));
            state.setToken(resultSet.getString(State.Fields.TOKEN.name()));
            state.setTitle(resultSet.getString(State.Fields.TITLE.name()));
            return state;
        }
    }

}
